<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>卫星绕月</title>
    <style>
      body {
        margin: 0;
      }
      #canvas {
        background-color: darkslateblue;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas" width="400" height="400">
      让我看看是谁不支持 canvas
    </canvas>

    <script>
      window.onload = function () {
        const canvas = document.getElementById('canvas')
        // 判断是否支持 canvas
        if (!canvas.getContext) {
          return
        }
        const ctx = canvas.getContext('2d')

        // 获取画布的宽高
        const width = canvas.width
        const height = canvas.height

        // 掘金logo
        const juejin = new Image()
        juejin.src =
          ''

        requestAnimationFrame(draw)

        function draw() {
          ctx.clearRect(0, 0, width, height) // 清除画布

          // 签名
          drawSignature()

          // 星星
          drawStar(100, 40, 1)
          drawStar(200, 60, 0.8)
          drawStar(300, 120, 0.6)
          drawStar(350, 300, 0.6)
          drawStar(60, 380, 0.5)
          drawStar(80, 320, 0.3)

          // 保存状态
          ctx.save()
          // 移动坐标系原点至画布中心
          ctx.translate(width / 2, height / 2)

          // 月球
          drawMoon()

          // 卫星轨迹
          drawTrajectory()

          const time = new Date()
          ctx.rotate(
            ((2 * Math.PI) / 60) * time.getSeconds() +
              ((2 * Math.PI) / 60000) * time.getMilliseconds()
          )

          // 卫星
          drawSatellite()

          // 恢复状态
          ctx.restore()

          requestAnimationFrame(draw)
        }

        // 绘制月球
        function drawMoon() {
          ctx.beginPath()
          ctx.arc(0, 0, 80, 0, Math.PI * 2)
          ctx.fillStyle = '#FEF1BC'
          ctx.fill()

          // 阴影
          drawShadow(80, '#F9E8A5')

          // 陨石坑
          drawMeteoriteCrater(-40, -30, 10)
          drawMeteoriteCrater(40, -30, 20)
          drawMeteoriteCrater(40, 40, 8)
        }

        // 绘制陨石坑
        function drawMeteoriteCrater(x, y, r) {
          ctx.save()
          ctx.translate(x, y)
          ctx.beginPath()
          ctx.arc(0, 0, r, 0, Math.PI * 2)
          ctx.fillStyle = '#F8E497'
          ctx.fill()
          // 阴影
          drawShadow(r, '#E6CE6F')
          ctx.restore()
        }

        // 绘制阴影
        function drawShadow(r, c) {
          ctx.save()
          ctx.rotate(-(Math.PI / 180) * 15)
          ctx.beginPath()
          ctx.arc(0, 0, r, 0, Math.PI / 2)
          ctx.bezierCurveTo(0.55 * r, 0.77 * r, 0.88 * r, 0.44 * r, r, 0)
          ctx.fillStyle = c
          ctx.fill()
          ctx.restore()
        }

        // 绘制卫星
        function drawSatellite() {
          ctx.save()
          ctx.translate(140, 0)
          ctx.scale(0.6, 0.6)
          ctx.rotate((Math.PI / 180) * 270)

          // 绘制三角形
          ctx.beginPath()
          ctx.moveTo(0, 0)
          ctx.lineTo(12, 14)
          ctx.lineTo(-12, 14)
          ctx.fillStyle = '#D8E0E5'
          ctx.fill()

          // 翅膀连接线
          ctx.fillRect(-17, 6, 34, 2)

          // 翅膀
          ctx.fillRect(17, 1, 20, 12)
          ctx.fillRect(-37, 1, 20, 12)

          // 掘金 logo   257 * 200
          ctx.drawImage(juejin, -6.425, 3, 12.85, 10)

          ctx.restore()
        }

        // 绘制签名
        function drawSignature() {
          ctx.font = '16px san-serif'
          ctx.fillStyle = 'rgba(255,255,255,0.6)'
          ctx.fillText('by: 亦黑迷失', 290, 380)
        }

        // 绘制星星
        function drawStar(x, y, r) {
          ctx.beginPath()
          ctx.arc(x, y, r, 0, Math.PI * 2)
          ctx.fillStyle = '#FEF1BC'
          ctx.fill()
        }

        // 绘制卫星轨迹
        function drawTrajectory() {
          ctx.beginPath()
          ctx.arc(0, 0, 143, 0, Math.PI * 2)
          ctx.strokeStyle = 'rgba(255,255,255,0.2)'
          ctx.setLineDash([4, 8])
          ctx.stroke()
        }
      }
    </script>
  </body>
</html>
